package com.bph.schedule.algorithm;

import java.util.Arrays;

/**
 * 按每0.5小时的店员需求量规划出一天实际需要的班次
 */
public class Lp{

    //更新可顺延班次表
    public static int[][] updateLive(int[][] lastlive,int[][] live){
        //旧班次
        for(int i=0;i<lastlive.length;i++){
            //更新已过2小时未被延长班次的生命周期
            if((lastlive[i][3] == live[i][3]) && live[i][3]>0){
                live[i][3] = 0;
            }
            //更新未过2小时的班次生命周期
            else if(lastlive[i][3] == live[i][3] && live[i][3]<0)
                live[i][3] += 1;
            //被延长的班次生命周期已在之前自主更新过
            else
                live[i][3] = live[i][3];

            if(live[i][3] == -1){//增到-1意味着2小时后面可以开始被延长了，故突变为4
                live[i][3] = (int)((Data.maxHour-Data.minHour)/0.5);
            }
            if(live[i][3] == 0){//0一定是由4减到0
                //todo 删除该元素，不删也行，只不过那样的话live[][]的长度就不能固定了
                //暂时先不删了，那就不用管它了，反正为0不会被选择
            }
        }
        return live;
    }

    public static double[][] adjust(int[] need){
        //每次调用该函数都排一天的，所以每次调用最后live这个每日班次顺延表都不再有意义，应该释放
        double[][] result = new double[28][];

        //可顺延的班次表{{0,1,4,3}}表示被排到第1个班次的第2个人，已工作4个0.5小时即2小时，生命周期为3
        //每轮被新排的班次默认2小时，然后加入顺延表中，初始生命周期-4
        //生命周期变化：-4->-2->-1---4->3->2->1->0
        //-4->0是因为2小时班次包括了4个半小时班次，而我们排班是按半小时半小时排的，
        // 达到预设的两小时后才可以被延长班次，而生命周期为正才可被顺延排班，因此达到-1的生命周期突变为4
        //每半小时的班次排班结束后，顺延表所有班次生命周期-1
        //todo 每次排班结束更新顺延表后都把生命周期为0的员工删掉，这里正是因为不好删，所以没删，
        // 也因此为了区分0是4减下来的还是-3加上去的，故从-4加到-1

        int[][] live = new int[1][4];
        //初始化为0
        for(int x=0;x<live.length;x++)
            Arrays.fill(live[x], 0);

        //开始为各半小时时间段安排班次
        for(int i=0;i<need.length;i++){
            if(need[i]!=0)
                result[i] = new double[need[i]];//根据店员需求量为排班表生成对应数量的单人班次
            else
                result[i] = new double[1];
            //初始化为0
            Arrays.fill(result[i], 0);

            //记录本次排班之前的live表，用于每次更新live表时比,来判断哪一个班次已经在被延长上班时间后自主更新过自己的生命周期
//                int[][] lastLive = live;
            //这里注意，如果写成让lastLive指向live，那么后面如果live变了，则lastLive也会变，因此无法起到前后对比效果
            //应该这么写
            int[][] lastLive = new int[live.length][4];
            for(int q=0;q< live.length;q++)
                for(int p=0;p<live[q].length;p++)
                    lastLive[q][p]=live[q][p];


            //需要need[i]个单人班次，则循环need[i]次
            for(int j=0;j<need[i];j++){
                //标志是否找到可以顺延班次，0为没有
                int flag = 0;
                //先遍历之前被排过班的班次表，看有没有可以被顺延到此班次的
                for(int b=0;b<lastLive.length;b++) {
                    //该班次新排的人（无论是否为顺延过来的）不会被再排
                    if (live[b][3] > 0 && live[b][3] == lastLive[b][3] && (8+live[b][0]*0.5+live[b][2]*0.5)==(8+0.5*i) ) {
                        result[live[b][0]][live[b][1]] += 0.5;//被选中的员工班次时长+0.5
                        live[b][2] += 1;//更新被延长班次的已工作时间,表示多了1个0.5小时
                        live[b][3] -= 1;//更新被延长的班次的生命周期
                        flag = 1;//告诉外面，找到可顺延的班次了，不用再新增员工
                        break; //选中一个就跳出结束循环，关闭顺延表
                    }
                }

                //没班次可被顺延，则新增一个最短时长班次
                if(flag == 0){
                    result[i][j] = Data.minHour;
                    //每次新增班次都应该更新need表（影响后续3个“半小时的班次”）
                    for(int d=i+1;d<i+(Data.minHour/0.5) && d<28;d++){
                        if(need[d]!=0)
                            need[d] -= 1;
                    }
                    //将刚排班2小时的班次加入顺延表live中，初始生命周期为-4
                    int len = live.length+1;//定长数组无法灵活延长，暂时只能拷贝到新数组了
                    int[][] newlive = new int[len][];
                    for(int z=0;z<live.length;z++){
                        newlive[z] = live[z];
                    }
                    newlive[len-1] = new int[]{i,j,(int)(Data.minHour/0.5),-((int)(Data.minHour/0.5))};
                    live = newlive;
                }
            }
            //更新顺延表
            live = Lp.updateLive(lastLive,live);
        }
        //释放数组资源？
        return result;
    }

    //测试代码
    public static void main(String[] args) {
        int[] need = {2,3,3,4,2,3,4,5,6,2,3,2,2,3,3,4,2,3,4,5,6,2,3,2,1,2,2,3};
        double[][] basic = Lp.adjust(need);
        int num = 0;
        String[][] finalNeed = new String[28][2];
        for(int i=0;i<basic.length;i++){
            System.out.println("第"+(i+1)+"个0.5小时");
            num += basic[i].length;
            finalNeed[i][0] = String.valueOf(8+0.5*i)+","+String.valueOf(8.5+0.5*i);
            finalNeed[i][1] = "";
            for(int j=0;j<basic[i].length;j++){
                System.out.print(basic[i][j]+"h-");
                finalNeed[i][1] += basic[i][j] +",";
            }
            System.out.println("\n"+"---------------------");
        }
        for(int k=0;k< finalNeed.length;k++)
            System.out.println(finalNeed[k][0]+":"+finalNeed[k][1]);
    }

}
